package cn.itcast.nems.manager.scrm;

import cn.itcast.ic.common.bean.Page;
import cn.itcast.nems.manager.auth.KeycloakConfig;
import cn.itcast.nems.manager.auth.KeycloakHelper;
import cn.itcast.nems.manager.scrm.dto.CollegeActivity;
import cn.itcast.nems.manager.scrm.dto.CollegeClue;
import cn.itcast.nems.manager.scrm.dto.CollegeClueAddResult;
import cn.itcast.nems.manager.scrm.dto.CustomerInfo;
import cn.itcast.nems.manager.util.OkHttpUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * author: yong.li
 * create: 2023-08-16 13:53:19
 **/
public class SCRMManager {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS).build();

    private final ObjectMapper objectMapper;
    private final KeycloakHelper keycloakHelper;
    private final String scrmDomain;

    public SCRMManager(String scrmDomain, KeycloakConfig keycloakConfig) {
        logger.info("SCRM init with scrmDomain: {} clientId: {}, tokenUrl: {}", scrmDomain, keycloakConfig.kcClientId(), keycloakConfig.kcTokenUrl());
        this.keycloakHelper = new KeycloakHelper(keycloakConfig);
        this.scrmDomain = scrmDomain.endsWith("/") ? scrmDomain : scrmDomain + "/";
        this.objectMapper = new ObjectMapper();
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 查询客户及归属人信息
     *
     * @param customerId scrm客户信息
     * @return 客户信息
     */
    public CustomerInfo findCustomerInfo(int customerId) {
        String url = this.scrmDomain + "oapi/customer/" + customerId;
        try {
            String token = this.keycloakHelper.getAccessToken();
            Request request = new Request.Builder()
                    .addHeader("Authorization", "Bearer " + token)
                    .url(url)
                    .build();
            final String response = this.sendHttpRequest(request);
            logger.info("get customer {} response:{}", customerId, response);
            if (StringUtils.hasText(response)) {
                final JsonNode res = objectMapper.readTree(response);
                final String errorMessage = res.path("errorMessage").asText();
                if (StringUtils.hasText(errorMessage)) {
                    throw new RuntimeException("查找客户'" + customerId + "'出现错误'" + errorMessage + "'");
                }
                return objectMapper.readValue(response, CustomerInfo.class);
            }
            return null;
        } catch (Exception e) {
            logger.warn("find customer '{}' error url '{}'", customerId, url);
            throw new RuntimeException(e);
        }
    }

    /**
     * 分页查询客户信息
     *
     * @param pageRequestJson 分页查询JSON条件
     * @return 客户分页信息
     */
    public Page<CustomerInfo> customerPageList(String pageRequestJson) {
        try {
            String token = this.keycloakHelper.getAccessToken();
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", "Bearer " + token);
            final String response = OkHttpUtil.doPost(this.scrmDomain + "oapi/customer/page/list", pageRequestJson, headers);
            logger.info("post customer page list response:{}", response);
            return objectMapper.readValue(response, Page.class);
        } catch (Exception e) {
            logger.warn("customer page list error, condition:{}", pageRequestJson);
            throw new RuntimeException(e);
        }
    }

    /**
     * 分页查询客户信息
     *
     * @param pageRequestJson 分页查询JSON条件
     * @return 客户分页信息
     */
    public Page<CollegeActivity> collegeActivityPageList(String pageRequestJson) {
        try {
            String token = this.keycloakHelper.getAccessToken();
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", "Bearer " + token);
            final String response = OkHttpUtil.doPost(this.scrmDomain + "oapi/college/activity/page/list", pageRequestJson, headers);
            logger.info("post college activity page list response:{}", response);
            return objectMapper.readValue(response, Page.class);
        } catch (Exception e) {
            logger.warn("college activity page list error, condition:{}", pageRequestJson);
            throw new RuntimeException(e);
        }
    }

    /**
     * 添加院校线索，如果手机号已经存在，则返回已存在客户ID
     *
     * @param collegeClue 院校线索
     * @return 客户ID
     */
    public CollegeClueAddResult addCollegeClue(@Validated CollegeClue collegeClue) {
        try {
            String token = this.keycloakHelper.getAccessToken();
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", "Bearer " + token);
            final String requestBody = objectMapper.writeValueAsString(collegeClue);
            logger.info("post add college clue request:{}", requestBody);
            final String response = OkHttpUtil.doPost(this.scrmDomain + "oapi/college/clue", requestBody, headers);
            logger.info("add college clue response:{}", response);
            if (StringUtils.hasText(response)) {
                final JsonNode res = objectMapper.readTree(response);
                final boolean success = res.get("success").asBoolean();
                if(success){
                    final JsonNode resultObject = res.get("resultObject");
                    return objectMapper.readValue(resultObject.toString(), CollegeClueAddResult.class);
                }
                final JsonNode errorMessage = res.path("errorMessage");
                if (!errorMessage.isNull()) {
                    throw new RuntimeException("添加客户'" + requestBody + "'出现错误'" + errorMessage.asText() + "'");
                }
            }
            throw new RuntimeException("scrm添加线索失败");
        } catch (Exception e) {
            logger.warn("add college clue error, collegeClue:{}", collegeClue, e);
            throw new RuntimeException(e);
        }
    }


    private String sendHttpRequest(Request request) {
        try (Response response = httpClient.newCall(request).execute()) {
            if (response.code() != 200) {
                logger.warn("SCRM responseCode:{} response:{} requestUrl:{}", response.code(), response, request.url());
            }
            final ResponseBody body = response.body();
            return body != null ? body.string() : "";
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
